#ifndef _CONNECTION_H_INCLUDED_
#define _CONNECTION_H_INCLUDED_
#include <list>
#include <memory>
#include "module/X6.h"
#include "module/responder.h"
#include "module/X7.h"
#include <sys/epoll.h>
#include <mutex>
/* 连接事件 */
const int UNUSED = 0; //未使用的，可以分配的连接
const int TOBEUSED = 1; //已经被分配的连接
const int LOCAL_CONNECTION = 1 << 1; //用户连接
const int PEER_CONNECTION = 1 << 2; //对端连接
const int DEFAULT_CONNECTION_POOL_SIZE = 100;

struct connection_t
{
    int fd = -1;
    int type = UNUSED;
    std::shared_ptr<X6> reader;
    std::shared_ptr<responder> writer;
    std::shared_ptr<X7> peerReader;
    bool isReady = false;
    socklen_t addrlen;
    sockaddr_in addr;
    uint32_t ev = 0; //存储epoll_event中的事件类型
    connection_t(){
       memset(&addrlen, 0, sizeof(addrlen));
    }
    void setConnnection(int _fd, int _type, X6* _reader, responder* _writer, bool _isReady){
        fd = _fd;
        memset(&addrlen, 0, sizeof(addrlen));
        if(_type >= UNUSED && _type <= PEER_CONNECTION)
            type = _type;
        reader.reset(_reader);
        writer.reset(_writer);
        isReady = _isReady;
    }
};

//线程安全的连接池
class connectionPool
{
private:
    using it_t = std::list<connection_t>::iterator;
    std::list<connection_t> connections;
    int numsAvailable;
    std::mutex connectionLock;

public:
    connectionPool():
    connections(DEFAULT_CONNECTION_POOL_SIZE), numsAvailable(DEFAULT_CONNECTION_POOL_SIZE){}
    connection_t* getFreeConnection()//从连接池中获取一个空连接
    {
        std::lock_guard<std::mutex> lock(connectionLock);
        if(numsAvailable == 0){
            connections.push_back(connection_t());
            numsAvailable++;
        }
        for(it_t it = connections.begin(); it != connections.end(); it++){
            if(it->type == UNUSED){
                it->type = TOBEUSED;
                numsAvailable--;
                return (connection_t*)&(*it);
            }
        }
    }
    //要修改
    void returnConnection(connection_t* theConnection)//向连接池归还连接
    {
        std::lock_guard<std::mutex> lock(connectionLock);
        theConnection->setConnnection(-1, UNUSED, nullptr, nullptr,false); 
        theConnection->ev = 0;
        theConnection->peerReader.reset();
        numsAvailable++;
    } 
};

#endif